﻿/*
 * Portions Copyright 2010 Andrew Bolson, Unknown License 
 *   (http://www.codeproject.com/Members/Andrew-Boisen)
 * ----- - - - - - - -- -- -- -- -- -- -- -- -- -- -- - - - - - - -----
 * Other Portions Copyright 2011 John M. Hollingsworth
 *   (http://www.jmhollingsworth.us/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

using log4net;

/// <summary>
/// handles Status file I/O operations in a consistent manner
/// </summary>
namespace EggTimerWithStatus
{
    class StatusIOWrapper
    {
        private static ILog log = null;
        private string statusFilePath = string.Empty;
        private string statusFileName = string.Empty;
        private DateTime fileTimestamp = DateTime.Now;

        // ctor
        public StatusIOWrapper() 
        {
            Logger logger = Logger.Instance;
            this.Log = logger.Log;
        }

        public void Configure()
        {
            if (this.StatusFileName == null || this.StatusFileName == string.Empty)
            {
                // TODO need to log out
                return;
            }
            DirectoryInfo pathInfo = new DirectoryInfo(this.StatusFilePath);
            if (!pathInfo.Exists)
            {
                // TODO Use current pathing
            }
            else
            {
                string combinedFile = this.StatusFilePath + this.StatusFileName;
                FileInfo fileInfo = new FileInfo(combinedFile);
                if (!fileInfo.Exists)
                {
                    // FIXME: Combine with logic below based around dateCheckPassed and alter accordingly
                    // Create the file
                    string starterLine = "-----=== EggTimer Status Log for " + DateTime.Now + " created ===-----";
                    bool didStatusUpdate = fileReaderWriter(combinedFile, starterLine, false);
                    Log.Info("New file created at " + combinedFile);
                    Log.Debug("Status file header dumped with \"" + starterLine + "\"");
                }
                else
                {
                    // Check the file date. If it is not extant within today's date, copy it to it's 
                    // 'touch' date before making a new one.
                    bool dateCheckPassed = false;
                    DateTime now = DateTime.Now;
                    if (fileInfo.CreationTime.Year == now.Year &&
                        fileInfo.CreationTime.Month == now.Month &&
                        fileInfo.CreationTime.Day == now.Day)
                    {
                        dateCheckPassed = true;
                    }
                    if (!dateCheckPassed)
                    {
                        //Log.Debug(fileInfo.DirectoryName + " -- " + fileInfo.Name + " -- " + fileInfo.Extension);
                        string pureName = fileInfo.Name.Substring(0,(fileInfo.Name.Length-fileInfo.Extension.Length));
                        Log.Debug("pureName: " + pureName);
                        string nameWithDate = fileInfo.DirectoryName + "\\" + pureName + "-" +
                            now.Year.ToString() + now.Month.ToString() + now.Day.ToString() +
                            fileInfo.Extension;
                        FileStream fs = new FileStream(combinedFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                        StreamReader sr = new StreamReader(fs);
                        char[] cb = new char[fs.Length];
                        if (sr.Peek() > -1)
                        {
                            sr.Read(cb, 0, Int32.Parse(fs.Length.ToString()));
                        }
                        sr.Close();
                        StreamWriter sw = new StreamWriter(new FileStream(nameWithDate, FileMode.Append, FileAccess.Write, FileShare.ReadWrite));
                        sw.Write(cb);
                        sw.Flush();
                        sw.Close();
                        File.Delete(combinedFile);
                    }
                    string starterLine = "-----=== EggTimer Status Log for " + DateTime.Now;
                    if (!dateCheckPassed)
                    {
                        starterLine += " created";
                    }
                    starterLine += " ===-----";
                    bool didStatusUpdate = fileReaderWriter(combinedFile, starterLine, dateCheckPassed);
                    Log.Info("File updated."); 
                    Log.Debug("Status file updated with \"" + starterLine + "\"");
                }
            }
        }

        /// <summary>
        ///         /// 
        /// </summary>
        /// <param name="inputLine"></param>
        /// <param name="previousLines">Must be composite of previous lines in String format. Make optional via sending null</param>
        /// <returns></returns>
        private bool fileReaderWriter(String combinedFileName, String inputLine, bool shouldAttemptReadPreviousLines)
        {
            bool rtn = true;
            StringBuilder sb = new StringBuilder();

            try
            {
                if (shouldAttemptReadPreviousLines)
                {
                    FileStream combinedFileStream = new FileStream(combinedFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                    StreamReader reader = new StreamReader(combinedFileStream);
                    char[] readerBuffer = new char[combinedFileStream.Length];
                    int readCount = reader.ReadBlock(readerBuffer, 0, readerBuffer.Length);
                    reader.Close();
                    if (readCount > 0)
                    {
                        sb.Append(readerBuffer);
                    }
                }
                StreamWriter writer = new StreamWriter(combinedFileName);
                sb.Append(inputLine);
                writer.WriteLine(sb.ToString());
                writer.Close();
            }
            catch (Exception ex)
            {
                Log.Error("Exception caught in StatusIOWrapper.fileReaderWriter:  " + ex.StackTrace);
                rtn = false;
            }

            return rtn;
        }

        public string StatusFilePath 
        {
            get { return statusFilePath; } 
            set 
            {
                if (!value.EndsWith("\\"))
                    this.statusFilePath = value + "\\";
                else
                    this.statusFilePath = value;
            } 
        }
        public string StatusFileName { get; set; }
        public DateTime FileTimestamp 
        {
            get { return this.fileTimestamp; }
        }
        public ILog Log { get; set; }
    }
}
